package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jdk.jfr.consumer.RecordedClass;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.weaver.ast.Var;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author mytjxt
 * @since 2024-05-21
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final LearningRecordMapper learningRecordMapper;

    @Override
    public void addUserLessons(Long userId, List<Long> courseIds) {
        //1.查询课程有效期
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(courseIds);
        //健壮性检测
        if (CollUtils.isEmpty(simpleInfoList)) {
            // 课程不存在，无法添加
            log.error("课程信息不存在，无法添加到课表");
            return;
        }
        //2.保存课程信息
        List<LearningLesson> learningLessons = new ArrayList<>();
        for (CourseSimpleInfoDTO infoDTO : simpleInfoList) {
            //2.1封装数据
            LearningLesson lesson = new LearningLesson();
            lesson.setUserId(userId);
            lesson.setCourseId(infoDTO.getId());
            Integer validDuration = infoDTO.getValidDuration();
            if (validDuration != null){
                LocalDateTime now = LocalDateTime.now();

                lesson.setExpireTime(now.plusMonths(validDuration));
                learningLessons.add(lesson);
            }
        }
         //2.2批量保存
            saveBatch(learningLessons);
    }

    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery pageQuery) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询我的课程
        //2.1分页查询课表
        Page<LearningLesson> lessonPage = lambdaQuery().
                eq(LearningLesson::getUserId, userId)
                .page(pageQuery.toMpPage("latest_learn_time", false));//默认排序
        //2.2获取分页结果
        List<LearningLesson> records = lessonPage.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(lessonPage);
        }

        //获取课程id集合
        List<Long> coursIds = records
                .stream()
                .map(LearningLesson::getCourseId)
                .collect(Collectors.toList());
        //2.3查询课程信息
        Map<Long, CourseSimpleInfoDTO> cMap = getCourseSimpleInfoDTOMap(coursIds);

        //封装vo
        List<LearningLessonVO> vos = new ArrayList<>();
        for (LearningLesson record : records) {
            LearningLessonVO learningLessonVO =
                    BeanUtils.copyBean(record, LearningLessonVO.class);
            CourseSimpleInfoDTO cDto = cMap.get(record.getCourseId());
            if (cDto != null){
                learningLessonVO.setCourseName(cDto.getName());
                learningLessonVO.setCourseCoverUrl(cDto.getCoverUrl());
                learningLessonVO.setSections(cDto.getSectionNum());
            }
            vos.add(learningLessonVO);
        }

        return PageDTO.of(lessonPage, vos);
    }

    private Map<Long, CourseSimpleInfoDTO> getCourseSimpleInfoDTOMap(List<Long> coursIds) {
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(coursIds);
        if (CollUtils.isEmpty(simpleInfoList)) {
            // 课程不存在，无法添加
            throw new BadRequestException("课程信息不存在！");
        }
        //将课程集合转换为map--避免双重for循环
        Map<Long, CourseSimpleInfoDTO> cMap = simpleInfoList
                .stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, infoDTO -> infoDTO));
        return cMap;
    }

    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询我的课程-最近一次课程
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();
        if (lesson == null) {
            return null;
        }
        //3.查询课程信息
        Map<Long, CourseSimpleInfoDTO>
                courseSimpleInfoDTOMap
                = getCourseSimpleInfoDTOMap(CollUtils.singletonList(lesson.getCourseId()));
        CourseSimpleInfoDTO
                courseSimpleInfoDTO = courseSimpleInfoDTOMap.get(lesson.getCourseId());
        if (courseSimpleInfoDTO == null){
            return null;
        }
        //4.计算我的总课程数
        Long courseId = lesson.getCourseId();
        Integer courseAmount = lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .count();
        //5.查小节--feign
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS =
                catalogueClient
               .batchQueryCatalogue(CollUtils.singletonList(lesson.getLatestSectionId()));
        if (CollUtils.isEmpty(cataSimpleInfoDTOS)){
            return null;
        }
        CataSimpleInfoDTO cataSimpleInfoDTO = cataSimpleInfoDTOS.get(0);

        //6.封装数据返回
    LearningLessonVO learningLessonVO = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        learningLessonVO.setCourseAmount(courseAmount);
        learningLessonVO.setCourseName(courseSimpleInfoDTO.getName());
        learningLessonVO.setCourseCoverUrl(courseSimpleInfoDTO.getCoverUrl());
        learningLessonVO.setSections(courseSimpleInfoDTO.getSectionNum());
        learningLessonVO.setLatestSectionName(cataSimpleInfoDTO.getName());
        learningLessonVO.setLatestSectionIndex(cataSimpleInfoDTO.getCIndex());

        return learningLessonVO;
    }

    @Override
    public Long isLessonValid(Long courseId) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询具体课程
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        if (lesson == null){
            return null;
        }
        LocalDateTime expireTime = lesson.getExpireTime();
        if (expireTime != null && expireTime.isBefore(LocalDateTime.now())){
            return null;
        }

        return lesson.getId();
    }

    @Override
    public LearningLessonVO queryLearningStatus(Long courseId) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.查询我的课程-具体课程
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        if (lesson == null){
            return null;
        }
        //3.封装返回
        LearningLessonVO learningLessonVO = BeanUtils.copyBean(lesson, LearningLessonVO.class);


        return learningLessonVO;
    }

    @Override
    public void createLearningPlan(Long courseId, Integer freq) {
        //有计划就不创建，修改频率
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
      //plan_status==1 updte set freq = #{freq} where user_id = #{userId} and course_id = #{courseId}
      //没有学习计划： updte set freq = #{freq} where user_id = #{userId} and course_id = #{courseId}
        boolean update = lambdaUpdate().set(LearningLesson::getWeekFreq, freq)
                .set(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING.getValue())
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId).update();
            if (!update){
            throw new BadRequestException("修改学习计划失败");
            }
    }

    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery query) {
        //1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.获取本周起始时间
        LocalDate now = LocalDate.now();
        LocalDateTime begin = DateUtils.getWeekBeginTime(now);
        LocalDateTime end = DateUtils.getWeekEndTime(now);
        //3.查询课表
        Page<LearningLesson> lessonPage = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING.getValue())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<LearningLesson> lessonPageRecords = lessonPage.getRecords();
        //根据课表获取 课程id集合
        List<Long> courseIds = lessonPageRecords.stream().map(lesson -> {
            Long courseId = lesson.getCourseId();
            return courseId;
        }).collect(Collectors.toList());
        //4.某课程本周已完成小节数，和总计本周已完成小节数
        // count () from learning_record where lesson_id = #{lessonId} and create_time between #{begin} and #{end}
        Integer   isFinishedSection = 0;
        HashMap<Long, Integer> map = new HashMap<>();
        List<Integer> weekCount = lessonPageRecords.stream().map(lesson -> {
            Integer count = learningRecordMapper.selectCount(
                    new LambdaQueryWrapper<LearningRecord>()
                            .eq(LearningRecord::getLessonId, lesson.getId())
                            .eq(LearningRecord::getFinished, true)
                            .gt(LearningRecord::getFinishTime, begin)
                            .lt(LearningRecord::getFinishTime, end)
            );
            map.put(lesson.getId(), count);
            return count;
        }).collect(Collectors.toList());
        for (Integer i : weekCount) {
            isFinishedSection=isFinishedSection+i;
        }

        //远程调用课程服务，获取课程信息->课程总节数
        Map<Long, CourseSimpleInfoDTO> courseSimpleInfoDTOMap
                = getCourseSimpleInfoDTOMap(courseIds);


        //5.封装数据
        Integer sumFreq =0;
        List<LearningPlanVO> voList = new ArrayList<>(lessonPageRecords.size());
        for (LearningLesson lessonPageRecord : lessonPageRecords) {
            LearningPlanVO learningPlanVO =   BeanUtils.copyBean(lessonPageRecord, LearningPlanVO.class);
            learningPlanVO.setCourseName(courseSimpleInfoDTOMap.get(learningPlanVO.getCourseId()).getName());
            learningPlanVO.setWeekLearnedSections(map.get(lessonPageRecord.getId()));//本周已学习小节数量
            learningPlanVO.setSections(courseSimpleInfoDTOMap.get(learningPlanVO.getCourseId()).getSectionNum());
            voList.add(learningPlanVO);
            sumFreq= sumFreq + lessonPageRecord.getWeekFreq();


        }
        LearningPlanPageVO  learningPlanPageVO = new LearningPlanPageVO();
        learningPlanPageVO.setWeekTotalPlan(sumFreq);
        learningPlanPageVO.setWeekPoints(0);
        learningPlanPageVO.setWeekFinished(isFinishedSection);
        learningPlanPageVO.pageInfo(lessonPage.getTotal(),lessonPage.getPages(), voList);

        return learningPlanPageVO;


    }


}
